home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / DDJ0192.ARJ / DISKDUP.ASC < prev    next >
Text File  |  1991-11-21  |  21KB  |  868 lines

  1. _YOUR OWN DISK DUPLICATOR PROGRAM_
  2. by Al Williams
  3.  
  4. [LISTING ONE]
  5.  
  6. /****************************************************************
  7.  * CB386.H - include file for CopyBuilder 386                   *
  8.  * See makefile for compile directives -- Al Williams           *
  9.  ****************************************************************/
  10. #define NRTRIES 3         /* number of times to retry disk ops */
  11.  
  12. /* force codebuilder to not align */
  13. #pragma align(_bpb=1)
  14. /* structre of disk BPB */
  15. extern struct _bpb
  16.   {
  17.   unsigned char jump[3];
  18.   char oemname[8];
  19.   unsigned short bytespersec;
  20.   unsigned char secperclust;
  21.   unsigned short ressectors;
  22.   unsigned char nrfats;
  23.   unsigned short rootsize;
  24.   unsigned short nrsectors;
  25.   char media;
  26.   unsigned short fatsectors;
  27.   unsigned short secpertrack;
  28.   unsigned short nrheads;
  29.   unsigned int hiddensecs;
  30.   unsigned int hugesectors;
  31.   unsigned char physdrive;
  32.   char notused;
  33.   unsigned char signature;      /* should be 0x29 */
  34.   unsigned int serno;
  35.   char label[11];
  36.   char type[8];
  37.   char pad[512-60];             /* rest of 512 byte sector */
  38.   } bpb;
  39. /* various globals */
  40. extern int driveno;
  41. extern unsigned disksize;
  42. extern unsigned sectorct;
  43. /* disk image buffer */
  44. extern unsigned char *diskbuf;
  45. /* DOS buffer used to communicate with BIOS */
  46. extern char *dosbuf;
  47. /* set by critical errors */
  48. extern int critical_err;
  49. /* information on buffer */
  50. extern struct _bufinfo
  51.   {
  52.   char title[65];
  53.   unsigned size;
  54.   unsigned short copies;
  55.   char source[13];
  56. /* checksums (stored and computed) */
  57.   unsigned short csum, ccsum;
  58.   short dirty;
  59.   } bufinfo;
  60. extern void (*slbreak)();    /* place to hook break handler */
  61. /* holds disk format command */
  62. extern char fmtcmd[];
  63. /* additional break handler */
  64. extern void (*when_break)();
  65. /* prototypes for break handlers */
  66. void load_break();
  67. void save_break();
  68. /* general prototypes */
  69. int sector_read(int head, int track, int sector, int drive,
  70.             unsigned char *buf,unsigned count);
  71. int sector_write(int head, int track, int sector, int drive,
  72.             unsigned char *buf,unsigned count);
  73. /* disable reboot */
  74. void noreboot(void);
  75. void okreboot(void);
  76.  
  77.  
  78.  
  79.  
  80. [LISTING TWO]
  81.  
  82.  
  83. /****************************************************************
  84.  * CB386.C - main file for CopyBuilder 386                      *
  85.  * See makefile for compile directives -- Al Williams           *
  86.  ****************************************************************/
  87. #include <stdio.h>
  88. #include <dos.h>
  89. #include <ctype.h>
  90. #include "cb386.h"
  91. #include "display.h"
  92.  
  93. /* current drive number */
  94. int driveno;
  95. /* current bios parameter block */
  96. struct _bpb bpb;
  97. /* size of disk */
  98. unsigned disksize;
  99. /* information about buffer */
  100. struct _bufinfo bufinfo;
  101. /* number of sectors */
  102. unsigned sectorct;
  103. /* storage for disk image */
  104. unsigned char *diskbuf;
  105. /* set when a critical error occurs */
  106. int critical_err;
  107. /* DOS buffer for disk BIOS reads and writes */
  108. char *dosbuf;
  109. /* text of format command */
  110. char fmtcmd[129];
  111. /* set when a critical error occurs */
  112. int critical_err;
  113. /* critical error messages */
  114. static char *cmsgs[]=
  115.   {
  116.   "Write protect",
  117.   "Unknown unit",
  118.   "Drive not ready",
  119.   "Unknown command",
  120.   "CRC error",
  121.   "Bad Request",
  122.   "Seek error",
  123.   "Unknown media",
  124.   "Sector not found",
  125.   "Out of paper",
  126.   "Write error",
  127.   "Read error",
  128.   "General failure",
  129.   "Unknown",
  130.   "Unknown",
  131.   "Invalid change"
  132.   };
  133. /* Critical error handler */
  134. void cerror(int dev,int code)
  135.   {
  136.   char msg[81];
  137.   int choice;
  138.   critical_err=code&=0xFF;
  139.   sprintf(msg,"Critical error: %s (Retry, Fail, Ignore)", cmsgs[code]);
  140.   choice=prompt(msg,"RIF",ERRCOLOR);
  141.   if (choice==0) choice=_HARDERR_RETRY;
  142.   else if (choice==1) choice=_HARDERR_IGNORE;
  143.   else choice=_HARDERR_FAIL;  /* F or ESC */
  144.   _hardresume(choice);
  145.   }
  146. /* main program */
  147. main(int argc,char *argv[])
  148.   {
  149. /* set up critical error handler */
  150.   _harderr(cerror);
  151.   if (argc>2||argv[1][0]=='?'||argv[1][1]=='?')
  152.     error("CopyBuilder 386 by Al Williams\n"
  153.           "A diskette duplication system\n"
  154.           "Usage: CB386 [drive]\n");
  155. /* save current drive/directory */
  156.   cdsave();
  157. /* set up video mode and detect monitor type */
  158.   vidmode();
  159. /* if mono monitor, set up neutral colors */
  160.   if (mono)
  161.     {
  162.     TEXTCOLOR=7;
  163.     SOCOLOR=0x70;
  164.     ERRCOLOR=1;
  165.     HELPCOLOR=7;
  166.     }
  167. /* reset title, etc. */
  168.   strcpy(bufinfo.title,"<EMPTY>");
  169.   strcpy(bufinfo.source,"N/A");
  170.   strcpy(fmtcmd,"format");
  171.   noreboot();
  172. /* if user asked for a disk on the command line, read it */
  173.   if (argc==2)
  174.     {
  175. /* show a display */
  176.     disp();
  177. /* read the disk */
  178.     read_disk(*argv[1]);
  179.     }
  180. /* goto main menu */
  181.   menu();
  182.   }
  183. /* Non-interactive error routine */
  184. error(char *s)
  185.   {
  186.   printf("\n%s\n",s);
  187.   cdrestore();
  188.   exit(1);
  189.   }
  190. /* compute checksum
  191.    add sixteen bit words and wrap carry around */
  192. checksum()
  193.   {
  194.   unsigned char *bufp=diskbuf;
  195.   int i=bufinfo.size;
  196.   unsigned short cksum=0;
  197.   unsigned cksum1;
  198.   while (i--)
  199.     {
  200.     cksum1=cksum;
  201.     cksum1+=*bufp++;
  202.     cksum=cksum1&0xFFFF;
  203.     if (cksum1&0xFFFF0000)
  204.       cksum++;
  205.     }
  206.   bufinfo.ccsum=cksum;
  207.   return cksum;
  208.   }
  209. /* Format a disk in the indicated drive */
  210. format(int driveno)
  211.   {
  212.   char fcmd[80];
  213.   int stat;
  214. /* build command line */
  215.   sprintf(fcmd,"%s %c:",fmtcmd,driveno+'A');
  216. /* save video */
  217.   vidsave();
  218. /* execute command */
  219.   stat=system(fcmd);
  220.   vidrestore();
  221.   if (stat==-1) advise("Unable to execute format program");
  222.   }
  223. /* turn the blinking -wait- on at bottom of screen */
  224. wait_on()
  225.   {
  226.   int ocolor=color;
  227.   color=SOCOLOR|0x80;   /* make it blink */
  228.   goxy(0,24);
  229.   clreol();
  230.   goxy(37,24);
  231.   printfc("-WAIT-");
  232.   curshide();
  233.   color=ocolor;
  234.   }
  235. /* turn the blinking -wait- off at bottom of screen */
  236. wait_off()
  237.   {
  238.   goxy(0,24);
  239.   clreol();
  240.   }
  241.  
  242.  
  243.  
  244. [LISTING THREE]
  245.  
  246. /****************************************************************
  247.  * FILEIO.C File oriented I/O routines for CB386                *
  248.  * See makefile for compile directives -- Al Williams           *
  249.  ****************************************************************/
  250. #include <stdio.h>
  251. #include <malloc.h>
  252. #include <errno.h>
  253. #include "cb386.h"
  254. #include "display.h"
  255.  
  256. void (*slbreak)();   /* place to hook break handler */
  257.  
  258. /* ^C handler when saving -- used in DISKIO.C too */
  259. void save_break()
  260.   {
  261.   advise("\aOperation aborted");
  262.   if (slbreak) slbreak();
  263.   when_break=slbreak;
  264.   }
  265. /* ^C handler when loading -- used in DISKIO.C too */
  266. void load_break()
  267.   {
  268.   cleanup();
  269.   when_break=slbreak;
  270.   }
  271. /* Clean up an aborted load */
  272. cleanup()
  273.   {
  274.   if (diskbuf) free(diskbuf);
  275.   diskbuf=NULL;
  276.   memset(&bufinfo,0,sizeof(bufinfo));
  277.   strcpy(bufinfo.title,"<EMPTY>");
  278.   strcpy(bufinfo.source,"N/A");
  279.   }
  280. /* save disk image to a file */
  281. m_save()
  282.   {
  283.   slbreak=when_break;
  284.   when_break=save_break;
  285.   saveit();
  286.   when_break=slbreak;
  287.   slbreak=NULL;
  288.   }
  289. /* load disk image to a file */
  290. m_load()
  291.   {
  292.   slbreak=when_break;
  293.   when_break=load_break;
  294.   loadit();
  295.   when_break=slbreak;
  296.   slbreak=NULL;
  297.   }
  298. /* actual routine to save data */
  299. saveit()
  300.   {
  301.   char fn[66];
  302.   FILE *f=NULL;
  303.   int cnt1;
  304. /* if no data to save, forget it */
  305.   if (!diskbuf)
  306.     {
  307.     advise("No disk image in memory");
  308.     return;
  309.     }
  310. /* get a file name */
  311.   if (!getfilen(fn,65)) return;
  312.   critical_err=0;
  313. /* check if the file already exists */
  314.   if (!access(fn,0))
  315.     {
  316.     if (prompt("\aFile exists. Overwrite? (Y/N)"
  317.                ,"NY",TEXTCOLOR)<=0)
  318.       return;
  319.     }
  320. /* if checking for the file caused a critical error,
  321.    don't even try to open the file */
  322.   if (!critical_err) f=fopen(fn,"wb");
  323.  
  324. /* if the file can't be opened (or wasn't because of
  325.    a critical error, forget it */
  326.   if (!f)
  327.     {
  328.     advise("Can't open file for writing");
  329.     return;
  330.     }
  331. /* Get a title */
  332.   if (ask("Title: ",NULL,TEXTCOLOR,64,fn,NULL)==-1) return;
  333. /* only change title if new one was entered */
  334.   if (*fn) strcpy(bufinfo.title,fn);
  335. /* Turn the wait indicator on */
  336.   wait_on();
  337.   /* set dirty bit in image. copies/source/csum are meaningless */
  338.   bufinfo.dirty=1;
  339. /* write signature */
  340.   putw('C386',f);
  341. /* write size of bufinfo */
  342.   putw(sizeof(struct _bufinfo),f);
  343. /* write bufinfo */
  344.   fwrite(&bufinfo,1,sizeof(struct _bufinfo),f);
  345. /* write entire buffer in one swoop */
  346.   cnt1=fwrite(diskbuf,1,bufinfo.size,f);
  347. /* one | is deliberate here -- we always want to fclose */
  348.   if (ferror(f)|fclose(f)|(cnt1!=bufinfo.size))
  349.     advise("\aError writing to file");
  350.   else
  351.     bufinfo.dirty=0;
  352.   wait_off();
  353.   }
  354. /* routine to actually load file to disk image */
  355. loadit()
  356.   {
  357.   char fn[66];
  358.   FILE *f;
  359.   int cnt,cnt1;
  360. /* if buffer is full, confirm */
  361.   if (!dirtyquery()) return;
  362. /* get file name */
  363.   if (!getfilen(fn,65)) return;
  364. /* open it */
  365.   f=fopen(fn,"rb");
  366. /* can't open it, forget it */
  367.   if (!f)
  368.     {
  369.     advise("Can't open file");
  370.     return;
  371.     }
  372. /* Turn wait indicator on */
  373.   wait_on();
  374. /* check file type */
  375.   cnt=getw(f);
  376.   if (cnt!='C386')
  377.     {
  378.     advise("Not a C386 image file");
  379.     return;
  380.     }
  381. /* get size of bufinfo structure */
  382.   cnt=getw(f);
  383. /* new versions of C386 can't make bufinfo smaller, only larger
  384.    at the end */
  385.   fread(&bufinfo,1,cnt,f);
  386. /* kill old image */
  387.   if (diskbuf) free(diskbuf);
  388. /* allocate new image based on size */
  389.   diskbuf=malloc(bufinfo.size);
  390.   if (!diskbuf)
  391.     {
  392.     advise("Insufficient memory");
  393.     cleanup();
  394.     fclose(f);
  395.     return;
  396.     }
  397. /* read it all in */
  398.   cnt1=fread(diskbuf,1,bufinfo.size,f);
  399. /* one | is deliberate here also (see saveit(), above) */
  400.   if (ferror(f)|fclose(f)|(cnt1!=bufinfo.size))
  401.     {
  402.     advise("Error reading file");
  403.     cleanup();
  404.     return;
  405.     }
  406.   checksum();
  407.   strcpy(bufinfo.source,fn);
  408.   bufinfo.copies=0;
  409.   wait_off();
  410.   }
  411.  
  412.  
  413.  
  414.  
  415.  
  416. [LISTING FOUR]
  417.  
  418. /****************************************************************
  419.  * REBOOT.C - Disable ^ALT-DEL for CodeBuilder programs         *
  420.  * Al Williams -- August 1991                                   *
  421.  ****************************************************************/
  422. #include <stdio.h>
  423. #include <i32.h>
  424. #include <stk.h>
  425. #include <dos.h>
  426. #include <conio.h>
  427.  
  428. /* When running DOS we replace the keyboard interrupt
  429.    (INT 9) */
  430. /* old INT 9 handler */
  431. static void (*oldint9)();
  432. #pragma interrupt(ourint9)
  433. /* replacement interrupt handler */
  434. static void ourint9()
  435.   {
  436.   int code,temp;
  437. /* pointer to CodeBuilder stack frames */
  438.   _XSTACK *frame=_get_stk_frame();
  439. /* pointer to BIOS shift status byte */
  440.   unsigned char *shift_status=(unsigned char *)0x417;
  441. /* read keyboard */
  442.   code=inp(0x60);
  443. /* DEL is scan code 0x53 -- if *shift_status&0xc==0xc then shift
  444.    and Alt are down */
  445.   if (code!=0x53||(*shift_status&0xc)!=0xc) _chain_intr(oldint9);
  446. /* will not allow ^ALT-DEL */
  447. /* consume key from keyboard */
  448.   temp=inp(0x61);
  449.   outp(0x61,temp|0x80);
  450.   outp(0x61,temp);
  451.   outp(0x20,0x20);
  452. /* Tell CodeBuilder not to reissue interrupt */
  453.   frame->opts=_STK_NOINT;
  454.   return;
  455.   }
  456. /* This function locks the page ourint9 is on so it can't be swapped out. 
  457.    4K is the minimum size, and surely ourint9 isn't that big.... */
  458. static lockint9(int flag)
  459.   {
  460.   static lock=0;
  461.   if (flag!=lock)
  462.     {
  463.     lock=flag;
  464.     if (flag)
  465.       _dpmi_lockregion(ourint9,4096);
  466.     else
  467.       _dpmi_unlockregion(ourint9,4096);
  468.     }
  469.   }
  470. /********************** External interfaces ******************/
  471. /* Disable ^ALT-DEL */
  472. void noreboot()
  473.   {
  474.   lockint9(1);
  475.   oldint9=_dos_getvect(9);
  476.   _dos_setvect(9,ourint9);
  477.   }
  478. /* Enable ^ALT-DEL */
  479. void okreboot()
  480.   {
  481.   lockint9(0);
  482.   _dos_setvect(9,oldint9);
  483.   }
  484.  
  485.  
  486.  
  487.  
  488. [LISTING FIVE]
  489.  
  490. /****************************************************************
  491.  * DISPLAY.C general purpose Microsoft C text display library   *
  492.  * See also DISPLAY.H DIRPICK.C, and HISTO.C -- Al Williams     *
  493.  ****************************************************************/
  494. #include <stdio.h>
  495. #include <dos.h>
  496. #include <string.h>
  497. #include <stdarg.h>
  498. #include "display.h"
  499.  
  500. /* global variable sets color of output */
  501. int color=7;
  502. /* primary colors for color monitor (see display.h) */
  503. int colors[4]={ 0x1e, 0x70, 0x1c, 0x7e };
  504. /* 1=mono monitor, 0=color, -1=unknown */
  505. int mono=-1;
  506. /* set video mode and detect mono monitor
  507.    this should always be called first */
  508. void vidmode()
  509.   {
  510.   union REGS r;
  511.   if (mono<0)
  512.     {
  513.     r.h.ah=0xf;
  514.     int86(0x10,&r,&r);
  515.     mono=r.h.al==7;
  516.     }
  517.   r.x.ax=mono?7:3;
  518.   int86(0x10,&r,&r);
  519.   r.x.ax=0x500;
  520.   int86(0x10,&r,&r);
  521.   }
  522. /* goto point x,y (from 0-79 and 0-24) */
  523. void goxy(int x,int y)
  524.   {
  525.   union REGS r;
  526.   r.h.ah=2;
  527.   r.h.dh=y;
  528.   r.h.dl=x;
  529.   r.h.bh=0;
  530.   int86(0x10,&r,&r);
  531.   }
  532. /* clear screen region */
  533. void clears(int x0, int y0,int x1,int y1)
  534.   {
  535.   union REGS r;
  536.   r.x.ax=0x600;
  537.   r.h.bh=color;
  538.   r.h.ch=y0;
  539.   r.h.cl=x0;
  540.   r.h.dh=y1;
  541.   r.h.dl=x1;
  542.   int86(0x10,&r,&r);
  543.   goxy(0,0);
  544.   }
  545. /* get x,y position */
  546. void getxy(int *x,int *y)
  547.   {
  548.   union REGS r;
  549.   r.h.ah=3;
  550.   r.h.bh=0;
  551.   int86(0x10,&r,&r);
  552.   *x=r.h.dl;
  553.   *y=r.h.dh;
  554.   }
  555. /* write count characters
  556.    -- handle \r, \n, backspace, and \a
  557.    updates the cursor if count==1 (w/o line wrap)
  558.    otherwise, the cursor doesn't move */
  559. void writecc(int c,int count)
  560.   {
  561.   union REGS r;
  562. /* PS/2 BIOS tries to print 0 characters! */
  563.   if (count<=0) return;
  564. /* if bell character... */
  565.   if (c=='\a')
  566.     {
  567. /* use function 0eH to do count bells */
  568.     while (count--)
  569.       {
  570.       r.x.ax=0xe00|'\a';
  571.       r.x.bx=0;
  572.       int86(0x10,&r,&r);
  573.       }
  574.     return;
  575.     }
  576. /* if regular character (not \n or \r or bs) */
  577.   if (c!='\n'&&c!='\r'&&c!=8)
  578.     {
  579. /* print regular character */
  580.     r.h.ah=9;
  581.     r.h.al=c;
  582.     r.h.bh=0;
  583.     r.h.bl=color;
  584.     r.x.cx=count;
  585.     int86(0x10,&r,&r);
  586. /* if count isn't 1 return else do cursor update
  587.    NOTE: \n \r always update cursor */
  588.     if (count!=1) return;
  589.     }
  590. /* get cursor position */
  591.   r.h.ah=3;
  592.   r.h.bh=0;
  593.   int86(0x10,&r,&r);
  594. /* if \r, zero x coordinate
  595.    Note that 100 \r's is the same as 1 */
  596.   if (c=='\r')
  597.     r.h.dl=0;
  598. /* if \n, increment y coordinate by count */
  599.   else if (c=='\n')
  600.     r.h.dh+=count;
  601. /* if backspace back up by count or to start of line */
  602.   else if (c==8)
  603.     r.h.dl-=r.h.dl>count?count:r.h.dl;
  604.   else
  605. /* bump x coordinate. Assume it won't wrap over */
  606.     r.h.dl++;
  607.   r.h.ah=2;
  608.   int86(0x10,&r,&r);
  609.   }
  610. /* write a string using writec, a writecc macro
  611.    (see display.h) */
  612. void writes(char *s)
  613.   {
  614.   while (*s) writec(*s++);
  615.   }
  616. /* printf using writecc max length 99 */
  617. int printfc(char *fmt,...)
  618.   {
  619.   int rc;
  620.   char outbuf[100];
  621.   va_list aptr;
  622.   va_start(aptr,fmt);
  623.   rc=vsprintf(outbuf,fmt,aptr);
  624.   writes(outbuf);
  625.   return rc;
  626.   }
  627. /* prompt for single key @ coordinates x,y
  628.    use str as prompt, resp is valid keys, pcolor
  629.    is the color to use (0 for same color). Alpha characters
  630.    in resp should be upper case. If resp is "" then all
  631.    characters are valid. If resp is NULL then any alpha
  632.    character is valid.
  633.    returns:
  634.    -1 if ESC pressed
  635.    index of character if resp is valid
  636.    character if resp is NULL or ""
  637.    */
  638. int prompt_at(int x, int y, char *str,char *resp,int pcolor)
  639.   {
  640.   int ocolor,c;
  641.   char *index;
  642.   goxy(x,y);
  643.   ocolor=color;
  644.   if (pcolor) color=pcolor;
  645. /* clear to end of line */
  646.   clreol();
  647.   writes(str);
  648.   while (1)
  649.     {
  650. /* get key */
  651.     c=getch();
  652.     if (!c)
  653.       {
  654. /* ignore extended keys */
  655.       getch();
  656.       continue;
  657.       }
  658. /* if esc quit */
  659.     if (c==27) break;
  660. /* shift upper */
  661.     c=toupper(c);
  662. /* if resp in not null, check it */
  663.     if (resp&&(index=strchr(resp,c))) break;
  664. /* if resp is null, check for alpha */
  665.     if (resp==NULL&&isalpha(c)) break;
  666. /* if resp=="" then anything is OK */
  667.     if (resp&&!*resp) break;
  668.     }
  669.   color=ocolor;
  670.   goxy(x,y);
  671.   clreol();
  672.   curshide();
  673.   return c==27?-1:resp&&*resp?index-resp:c;
  674.   }
  675. /* prompt for input @x,y. Prompt with promptstr valid is a string of valid 
  676.    input characters (if NULL, all characters are OK., clr is the color 
  677.    (0 for same), len is the input length, buf is the buffer (should be at 
  678.    least len+1 long, and help is an optional help string (use NULL for the 
  679.    default help). returns: -1 if ESC # of characters input otherwise
  680.    You can use the backspace key to edit entries */
  681. int ask_at(int x, int y, char *promptstr,char *valid,
  682.       int clr,int len,char *buf,char *help)
  683.   {
  684.   int count=0,c,ocolor=color;
  685.   char *bp=buf;
  686. /* clear buffer */
  687.   memset(buf,0,len+1);
  688. /* set color, goto input line, and clear it */
  689.   if (clr) color=clr;
  690.   goxy(x,y);
  691.   clreol();
  692. /* write prompt */
  693.   writes(promptstr);
  694. /* main loop */
  695.   while (1)
  696.     {
  697. /* get a character. Extended keys are <0 */
  698.     c=getch();
  699.     if (!c) c=-getch();
  700. /* handle backspace */
  701.     if (c==8)
  702.       {
  703.       if (bp!=buf)
  704.         {
  705.         bp--;
  706.         writec(8);
  707.         writec(' ');
  708.         writec(8);
  709.         *bp='\0';
  710.         count--;
  711.         }
  712.       continue;
  713.       }
  714. /* Escape or enter ends input */
  715.     if (c=='\r'||c==27)
  716.       {
  717. /* restore color */
  718.       color=ocolor;
  719. /* clear line */
  720.       goxy(x,y);
  721.       clreol();
  722.       curshide();
  723. /* return */
  724.       return c==27?-1:count;
  725.       }
  726. /* If F1 give help */
  727.     if (c==-59)
  728.       {
  729.       vidsave();
  730.       prompt(help?help:
  731.       " Use <ENTER> to accept, <ESC> to quit, <Backspace>"
  732.          " to correct.","",SOCOLOR);
  733.       vidrestore();
  734.       continue;
  735.       }
  736. /* ignore other extended keys (c<0) or regular keys if
  737.    at input limit (count==len) */
  738.     if (count==len||c<0) continue;
  739. /* if not valid character, ignore */
  740.     if (valid&&!strchr(valid,c)) continue;
  741. /* echo input character */
  742.     writec(c);
  743. /* store in buffer */
  744.     *bp++=c;
  745. /* update count */
  746.     count++;
  747.     }
  748.   }
  749. /* routines to save and restore the video context */
  750. /* places to save things */
  751. static char vbuf[4096];
  752. static int save_xy,save_color;
  753. /* save video */
  754. void vidsave()
  755.   {
  756.   union REGS r;
  757.   save_color=color;
  758.   r.h.ah=3;
  759.   r.h.bh=0;
  760.   int86(0x10,&r,&r);
  761.   save_xy=r.x.dx;
  762.   memcpy((void *)vbuf,(void *)(mono?0xb0000:0xb8000),4096);
  763.   }
  764. /* restore video */
  765. void vidrestore()
  766.   {
  767.   union REGS r;
  768.   memcpy((void *)(mono?0xb0000:0xb8000),(void *)vbuf,4096);
  769.   color=save_color;
  770.   r.h.ah=2;
  771.   r.h.bh=0;
  772.   r.x.dx=save_xy;
  773.   int86(0x10,&r,&r);
  774.   }
  775.  
  776.  
  777.  
  778. [LISTING SIX]
  779.  
  780. /******************************************************************
  781.  * TIMING.C    -  simple non-rigorous benchmark for Phar Lap's    *
  782.  *                286 | DOS Extender & Intel 386 CodeBuilder      *
  783.  * Compile with:  ICC timing.c graphics.lib (386 protected mode)  *
  784.  * OR:                                                            *
  785.  * CL -AL -Lp -G2 -Ox timing.c graphp.obj llibpe.lib graphics.lib *
  786.  * (286 protected mode)                                           *
  787.  * OR:                                                            *
  788.  * CL -AL -G2 -Ox timing.c graphics.lib                           *
  789.  * (real mode)                                                    *
  790.  ******************************************************************/
  791. #include <stdio.h>
  792. #include <graph.h>
  793. #include <time.h>
  794.  
  795. #define time_mark time_it(0)
  796. #define time_done time_it(1)
  797.  
  798. main()
  799.   {
  800.   printf("Timing graphics operations\n");
  801.   time_mark;
  802.   gtest();
  803.   time_done;
  804.   printf("Timing file operations\n");
  805.   time_mark;
  806.   ftest();
  807.   time_done;
  808.   exit(0);
  809.   }
  810. /* Function to mark times */
  811. int time_it(int flag)
  812.   {
  813.   static clock_t sttime;
  814.   unsigned s;
  815.   if (!flag)
  816.     {
  817.     sttime=clock();
  818.     }
  819.   else
  820.     {
  821.     s=(clock()-sttime)/CLK_TCK;
  822.     printf("Elapsed time: %d seconds\n",s);
  823.     }
  824.   return 0;
  825.   }
  826. /* Graphics test -- must have VGA */
  827. int gtest()
  828.   {
  829.   int i,x,y;
  830.   _setvideomode(_MRES256COLOR);
  831.   for (i=1;i<11;i++)
  832.     {
  833.     _setcolor(i);
  834.     for (y=0;y<199;y++)
  835.       for (x=0;x<319;x++)
  836.         _setpixel(x,y);
  837.     }
  838.   _setvideomode(_DEFAULTMODE);
  839.   return 0;
  840.   }
  841. /* File test -- assumes 320K free on current drive */
  842. char filedata[64000];
  843. int ftest()
  844.   {
  845.   FILE *tfile;
  846.   int i,j;
  847.   for (j=0;j<10;j++)
  848.     {
  849.     tfile=fopen("~~TIMING.~@~","w");
  850.     if (!tfile)
  851.       {
  852.       perror("TIMING");
  853.       exit(1);
  854.       }
  855.     for (i=0;i<5;i++)
  856.       fwrite(filedata,sizeof(filedata),1,tfile);
  857.     if (fclose(tfile))
  858.       {
  859.       perror("TIMING");
  860.       }
  861.     unlink("~~TIMING.~@~");
  862.     }
  863.   return 0;
  864.   }
  865.  
  866.  
  867.  
  868.